﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EmailClient.DAO;
namespace EmailClient.FilterSpam
{
    public class NaiveBayes
    {
        public List<string> spamMails;//danh email spam
        public List<string> notSpamMails;//danh sach email not spam
        public int countSpamMails;//so email spam
        public int countNotSpamMails;//so email not spam
        public Parser parser;
        public Dictionary<string, int> sourceDictionarySpam;//load dictionary spam tu database
        public Dictionary<string, int> sourceDictionaryNotSpam;//load dictionary not spam tu database
        public Dictionary<string, int> desDictionaryNotSpam;//luu tru thong tin non spam xuong database 
        public Dictionary<string, int> desDictionarySpam;//luu tru thong tin spam xuong database 
        FilterSpamDAO filterSpamDAO;
        public string emailAddress;
        //load bo loc bayes
        public NaiveBayes(string emailAddress)
        {
            //init dictionary
            desDictionarySpam = new Dictionary<string, int>();
            desDictionaryNotSpam = new Dictionary<string, int>();
            sourceDictionaryNotSpam = new Dictionary<string, int>();
            sourceDictionarySpam = new Dictionary<string, int>();
            parser = new Parser();
            filterSpamDAO = new FilterSpamDAO();
            this.emailAddress = emailAddress;
            //load filterspam
            LoadFilterSpam();
        }
        /*
         * su dung khi kich hoat bo loc spam
         * Dữ liệu này dùng chung cho tất cả địa chỉ email khi kích hoạt 
         */
        public void TeachFilterSpam(string pathToFolderSpam, string pathToFolderNotSpam, EmailReader emailReader)
        {
            spamMails = emailReader.GetBodyEmailFromLocal(pathToFolderSpam);
            notSpamMails = emailReader.GetBodyEmailFromLocal(pathToFolderNotSpam);
            parser.wordCounter.Clear();
            //teach spam mail
            for (int i = 0; i < spamMails.Count; i++)
            {
                parser.UpdateDictionary(parser.Parse(spamMails[i]), desDictionarySpam);
                parser.wordCounter.Clear();
            }
            //teach not spam mail
            for (int i = 0; i < notSpamMails.Count; i++)
            {
                parser.UpdateDictionary(parser.Parse(notSpamMails[i]), desDictionaryNotSpam);
                parser.wordCounter.Clear();
            }
            countSpamMails = spamMails.Count();
            countNotSpamMails = notSpamMails.Count();
            //lưu thông tin bộ lọc vào database
            filterSpamDAO.AddInfoFilterSpam(desDictionarySpam, true, emailAddress);
            filterSpamDAO.AddInfoFilterSpam(desDictionaryNotSpam, false, emailAddress);
        }

        public void LoadFilterSpam()
        {
            sourceDictionarySpam = filterSpamDAO.LoadDictionary(emailAddress, true);
            sourceDictionaryNotSpam = filterSpamDAO.LoadDictionary(emailAddress, false);
        }
        //luu bo loc xuong database
        public void SaveFilterSpam(Dictionary<string, int> desDictionary, bool spam)
        {
            filterSpamDAO.UpdateDictionary(desDictionary, spam, emailAddress);
        }
        public bool CheckEmail(string text, string emailAddress)
        {
            //load dictionary
            /*
             * lưu ý: tính toán xác suất và lưu thông tin bộ lọc vào database 
             * từ trong thư mẫu khi install bộ lọc vào hệ thống.
             * không tính xác suất của thư mẫu khi get email về 
             */
            LoadFilterSpam();
            //check email spam
            return CheckIfSpam(text, countSpamMails, sourceDictionarySpam, countNotSpamMails, sourceDictionaryNotSpam);
        }

        private bool CheckIfSpam(string text,
            int countSpamMails, Dictionary<string, int> spamWordList,
            int countNotSpamMails, Dictionary<string, int> notSpamWordList)
        {
            var stringArray = text.Split(' ');
            var sumQ = 0.0;
            var wordCounter = 0;
            foreach (var item in stringArray)
            {
                var q = CalculateQ(item.ToLower(),
                    countSpamMails, sourceDictionarySpam,
                    countNotSpamMails, sourceDictionaryNotSpam);
                //update desDictionarySpam
                if (desDictionarySpam.ContainsKey(item))
                {
                    desDictionarySpam[item] += 1;
                }
                else
                {
                    desDictionarySpam.Add(item, 1);
                }
                //update desDictionaryNotSpam
                if (desDictionaryNotSpam.ContainsKey(item))
                {
                    desDictionaryNotSpam[item] += 1;
                }
                else
                {
                    desDictionaryNotSpam.Add(item, 1);
                }
                sumQ += q;
                wordCounter++;
            }
            //update dictionary

            //save dictionary
            if (sumQ / wordCounter > 1)
            {
                SaveFilterSpam(desDictionarySpam, true);
                return true;
            }
            else
            {
                SaveFilterSpam(desDictionaryNotSpam, false);
                return false;
            }
        }

        private double CalculateQ(string word,
            int countSpamMails, Dictionary<string, int> spamWordList,
            int countNotSpamMails, Dictionary<string, int> notSpamWordList)
        {
            double wordCountSpam = 1;
            if (spamWordList.ContainsKey(word))
            {
                wordCountSpam = spamWordList[word];
            }
            double Ph1e = 0.5 * wordCountSpam / countSpamMails;
            double wordCountNotSpam = 1;
            if (notSpamWordList.ContainsKey(word))
            {
                wordCountNotSpam = notSpamWordList[word];
            }
            double Ph2e = 0.5 * wordCountNotSpam / countNotSpamMails;
            double q = Ph1e / Ph2e;
            return q;
        }
    }
}
